﻿#include "ssMultiLineBuffer.h"
#include "../ssAssert.h"
#include <memory.h>

namespace StarSeeker
{

ssMultiLineBuffer::ssMultiLineBuffer()
{
	m_count = 0;
}

ssMultiLineBuffer::ssMultiLineBuffer(const ssMultiLineBuffer &oc)
	:m_pMem()
{
	m_count = 0;
	CopyFrom(oc);
}

ssMultiLineBuffer::~ssMultiLineBuffer()
{
	Clear();
}

void ssMultiLineBuffer::operator=(const ssMultiLineBuffer &oc)
{
	CopyFrom(oc);
}

bool ssMultiLineBuffer::Init(ulint size)
{
	if (size>0)
	{
		m_count = 0;
		return m_pMem.Init(size);
	}
	return false;
}

bool ssMultiLineBuffer::FormatIn(char *data, ulint size)
{
	if (size > 0)
	{
		char err = 0;
		ulint readSize = 0;
		ulint count = 0;
		while (err==0)
		{
			ulint* len = (ulint*)(data + readSize);
			++count;
			readSize += *len + cg_ulint_size;
			if (readSize == size)
			{
				err = 1;
			}
			else if (readSize > size)
			{
				err = 2;
			}
		}
		if (err == 1)
		{
			if (m_pMem.Init(data, size))
			{
				m_count = count;
				return m_pMem.SetSize(size);
			}
		}
	}
	return false;
}

bool ssMultiLineBuffer::PushBack(const void *data, ulint len)
{
	if (m_pMem.Size() + len + cg_ulint_size <= m_pMem.MaxSize())
	{
		memcpy(m_pMem.CurrentBuf(), &len, cg_ulint_size);
		m_pMem.AddSize(cg_ulint_size);
		memcpy(m_pMem.CurrentBuf(), data, len);
		m_pMem.AddSize(len);
		++m_count;
		return true;
	}
	else if (Resize((m_pMem.MaxSize() + len + cg_ulint_size) * 2))
	{
		memcpy(m_pMem.CurrentBuf(), &len, cg_ulint_size);
		m_pMem.AddSize(cg_ulint_size);
		memcpy(m_pMem.CurrentBuf(), data, len);
		m_pMem.AddSize(len);
		++m_count;
		return true;
	}
	return false;
}

StarSeeker::ulint ssMultiLineBuffer::Count() const
{
	return m_count;
}

StarSeeker::ulint ssMultiLineBuffer::Size() const
{
	return m_pMem.Size();
}

StarSeeker::ulint ssMultiLineBuffer::RemainSize()
{
	return m_pMem.ResidueSize();
}

const char* ssMultiLineBuffer::Buf() const
{
	return m_pMem.Buf();
}

bool ssMultiLineBuffer::Resize(ulint newSize)
{
	return m_pMem.Resize(newSize, true);
}

void ssMultiLineBuffer::Clear()
{
	m_count = 0;
	m_pMem.Clear();
}

//清空缓存
void ssMultiLineBuffer::Empty()
{
	m_count = 0;
	m_pMem.Empty();
}

ssMultiLineBuffer::Iterator ssMultiLineBuffer::Begin()
{
	Iterator itr;
	if (m_pMem.Size() > 0)
	{
		itr.pData = m_pMem.Buf() + cg_ulint_size;
		itr.nSize = *reinterpret_cast<ulint*>(m_pMem.Buf());
		itr.traversalCount = 1;
	}
	return itr;
}

bool ssMultiLineBuffer::Next(Iterator& itr)
{
	if (itr.traversalCount >= m_count || m_pMem.Size() == 0)
	{
		itr.Clear();
		return false;
	}

	ulint lastSize = itr.nSize;
	if (lastSize>m_pMem.Size())
	{
		SS_ASSERT_DEBUG(false);
		itr.Clear();
		return false;
	}
	itr.nSize = *reinterpret_cast<ulint*>(itr.pData+lastSize);
	itr.pData = itr.pData + lastSize + cg_ulint_size;
	++itr.traversalCount;
	return true;
}

void ssMultiLineBuffer::CopyFrom(const ssMultiLineBuffer &oc)
{
	Clear();
	m_pMem = oc.m_pMem;
	m_count = oc.m_count;
}

}
